Filtrovani kbmMemTable v druhem vlakne

Otázka od: Karel Pecinka

20. 10. 2004 19:10

Zdravim,
 
mam aplikaci, ve ktere uzivatel pise do Editu text a okamzite po napsani
se mu filtruje memory tabulka, ktera muze mit az 10.000 nebo vice radku.
U takoveho mnozstvi uz se stava, ze uzivatel napise rychle slovo a pak
musi cekat a vidi, jak se pomalu do editu pripisujou pismenka a zuzuje
se vyber. Je to sice pouzitelne, ale neni to prilis efektni.
 
Potreboval bych to vymyslet tak, aby uzivatel mohl nerusene psat a
filtrovani probihalo v jinem vlakne. Nebo napr. az kdyz pul sekundy
nepise. Zkousel jsem presouvat to filtrovani do druhyho vlakna, ale je
to problematicky, protoze to zase hlavni vlakno musi zobrazit a tak
dochazi ke konfliktum.
 
Poradite nekdo, jak se da vyresit tento problem?
 
Diky.
 
Karel


Odpovedá: Milan Tomes

20. 10. 2004 19:32

Ja bych to resil rozhodne pomoci prodlevy. Neni to celkem nic sloziteho -
mohu zaslat priklad pouziti...

S pozdravem

Milan Tomes

> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Karel Pecinka
> Sent: Wednesday, October 20, 2004 8:11 PM
>
> mam aplikaci, ve ktere uzivatel pise do Editu text a okamzite po napsani
> se mu filtruje memory tabulka, ktera muze mit az 10.000 nebo vice radku.
>
> filtrovani probihalo v jinem vlakne. Nebo napr. az kdyz pul sekundy
> nepise. Zkousel jsem presouvat to filtrovani do druhyho vlakna, ale je


Odpovedá: Ludek Finstrle

21. 10. 2004 9:01

> filtrovani probihalo v jinem vlakne. Nebo napr. az kdyz pul sekundy
> nepise.

Tady bych hodil timer do OnKeyDown ci Press nebo kam by se to nejvice
hodilo.

Luf


Odpovedá: Jan Novak

21. 10. 2004 21:10

> uzivatel pise do Editu text a okamzite po napsani
> se mu filtruje memory tabulka, ktera muze mit az 10.000

To je typicky priklad, kdy to vlakna jen zbytecne zakomplikuji.
Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.

Staci 2 staticke boolean promenne Nacitam a NovyFiltr, ktere pri
startu programu nastavis na false a pak Edit1.OnChange vypada nejak
takhle:

begin
if Nacitam then // zabraneni rekurze
  begin
   NovyFiltr := true;
   exit;
  end;
Nacitam := true;
repeat
  begin
   Radky.Zrus;
   Radky.Filtr := Edit1.Text; // aktualni filtr
   NovyFiltr := false;
   LastPM := Now;
   while not Radky.Hotovo do
    begin
      if NovyFiltr then break; // prerus nacitani po zmene editu
      Radky.NactiDalsi;
      if (Now-LastPM) > (200*MS) then
       begin // jednou za 200 ms
        LastPM := Now;
        Application.ProcessMessages;
       end;
    end;
  end until NovyFiltr;
Nacitam := false;
end;

MS je konstanta pro trvani milisekundy MS=1./(24*60*60*1000)


Odpovedá: Milan Tomes

22. 10. 2004 5:16

Tak tohle povazuji take za dost hruzne reseni.
Tady je reseni *BEZ* pouziti ProcessMessages:

interface

type
  TMyEdit = class (TEdit)
  private
    FOnLateChange: TNotifyEvent;
    FInterval: cardinal;
    FTimerHWND: HWND;
    procedure FinalizeTimer;
  protected
    procedure DoLateChange;
    procedure UpdateTimer;
    procedure WndProc(var Message: TMessage); override;
    procedure KeyPress(var Key: Char); override;
  public
    destructor Destroy; override;
  published
    property OnLateChange: TNotifyEvent read FOnLateChange write
FOnLateChange;
    property Interval: cardinal read FInterval write FInterval;
  end;

implementation

const
  UpdateTimer_IDEvent = 1;

{ TMyEdit }

destructor TMyEdit.Destroy;
begin
  FinalizeTimer;
  inherited;
end;

procedure TMyEdit.DoLateChange;
begin
  FinalizeTimer;
  if Assigned(FOnLateChange) then
    FOnLateChange(self);
end;

procedure TMyEdit.KeyPress(var Key: Char);
begin
  inherited;
  UpdateTimer;
end;

procedure TMyEdit.UpdateTimer;
begin
  FinalizeTimer;
  if Interval <> 0 then
    if setTimer(self.Handle, UpdateTimer_IDEvent, Interval, nil) = 0 then
      raise Exception.Create('Nelze vytvorit casovac !!!')
    else
      FTimerHWND := self.Handle;
end;

procedure TMyEdit.WndProc(var Message: TMessage);
begin
  if (Message.Msg = WM_TIMER) and (Message.WParam = UpdateTimer_IDEvent)
then
    DoLateChange
  else
    inherited;
end;

procedure TMyEdit.FinalizeTimer;
begin
  if FTimerHWND <> 0 then
  begin
    killTimer(FTimerHWND, UpdateTimer_IDEvent);
    FTimerHWND := 0;
  end;
end;

Interval je hodnota v milisekundach (- podivej se na WinAPI funkci
setTimer). Pokud je od prvniho stisku klavesy po dobu intervalu stisknuta
klavesa je timer zrusen a vzapeti znovu vytvoren (kvuli novemu pocitani
intervalu). V pripade klidu je po uplynuti zadaneho intervalu odeslana
timerem zprava WM_TIMER do WndProc a ta vyvola event OnLateChange.

S pozdravem

Milan Tomes

P.S.: Psal jsem to jen v Outlooku, takze nezarucuji funkcnost  

> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Jan Novak
> Sent: Thursday, October 21, 2004 10:11 PM
>
> > uzivatel pise do Editu text a okamzite po napsani
> > se mu filtruje memory tabulka, ktera muze mit az 10.000
>
> To je typicky priklad, kdy to vlakna jen zbytecne zakomplikuji.
> Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.


Odpovedá: Jan Novak

22. 10. 2004 6:44

>> Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.

> Tak tohle povazuji take za dost hruzne reseni.

Nezlob se na mne, ale to, cemu rikas 'reseni' ty, je jen nekolik
obrazovek sloziteho kodu, ktere nedelaji nic, nez ze po urcitem case
od zmeny Editu poslou zpravu hlavnimu threadu. Nemas tam vubec nic o
tom, jak se od ni v dalsim threadu nastartuje nacitani a jak se
pripadne prerusi predchozi nacitani, pokud bylo rozbehnuto. Neni tam
ani to, jak ten thread po nacteni jedne polozky zobrazi jeji obsah v
nejakem gridu, ktery je soucasti VCL a tedy se musi volat pres
Synchronize.

Zkus si to napsat cele a pak se vyslov, co je 'hruzne' a co je
prehledne a jasne reseni.


Odpovedá: Milan Tomes

22. 10. 2004 7:06

Cele reseni problemu je opravdu zalozeno na startovani timeru. Snazil jsem
se o reseni elementarniho problemu a sice toho aby se se zpozdenim vyvolala
udalost OnChange. Pokud se Ti toto nelibi, tak se prosim rychle uklidni a
prestan s takovymito vypady. Netvrdil jsem, ze je to reseni pomoci vlakna,
protoze se plne ztotoznuji, ze ve vlakne by - kdyz uz - melo probihat
vlastni cteni dat a ne zpracovani pauzy, ktera je uzce zavisla na VCL
komponente a tudiz veskere volani musi byt provadeno v kontextu hlavniho
threadu. Jestli je pro Tebe tento kod slozity je samozrejme otazka jina - ja
osobne vubec nechapu co je na tomto kodu sloziteho - jedna se o 6 metod
jejichz delka nepresahuje 6 jednoduchych radku kodu. BTW cely kod jsem psal
v Outlooku a jeho napsani netrvalo dele nez 5 minut  

Cele reseni jsem napsal a neustale povazuji Tve reseni za hruzne.

Omlouvam se, ze jsem hluboce urazil Tve city tim, ze jsem vyslovil svuj
nazor na kvalitu Tveho reseni. Az budes neco potrebovat Ty, tak verim, ze se
vsichni strasne pretrhnout kdyz vidi Tvoji reakci. Ja osobne nepomohu uz jen
proto, ze se budu obavat abys me nahodou za univerzalnost a tim take moznou
vetsi narocnost na znalosti a slozitost nahodou znovu neserval  

S pozdravem

Milan Tomes

P.S.: Tusim, ze tazatel to jiz vyresil prave vytvoreni one nove komponenty,
jejiz kod jsem posilal  
P.P.S.: Podivej se na thread, kde se pouziti Application.ProcessMessages
velice kritizuje.

> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Jan Novak
> Sent: Friday, October 22, 2004 7:45 AM
>
> >> Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.
>
> > Tak tohle povazuji take za dost hruzne reseni.
>
> Nezlob se na mne, ale to, cemu rikas 'reseni' ty, je jen nekolik
> obrazovek sloziteho kodu, ktere nedelaji nic, nez ze po urcitem case
> od zmeny Editu poslou zpravu hlavnimu threadu. Nemas tam vubec nic o
> tom, jak se od ni v dalsim threadu nastartuje nacitani a jak se
> pripadne prerusi predchozi nacitani, pokud bylo rozbehnuto. Neni tam
> ani to, jak ten thread po nacteni jedne polozky zobrazi jeji obsah v
> nejakem gridu, ktery je soucasti VCL a tedy se musi volat pres
> Synchronize.
>
> Zkus si to napsat cele a pak se vyslov, co je 'hruzne' a co je
> prehledne a jasne reseni.
>
>
>
>


Odpovedá: Karel Kral

22. 10. 2004 8:19

Diky, pekne a elegantni, urcite se mi to bude hodit. Proc nepouzivas
TTimer z Delphi?

Milan Tomes napsal(a):
> Tak tohle povazuji take za dost hruzne reseni.
> Tady je reseni *BEZ* pouziti ProcessMessages:
>
> interface
>
> type
> TMyEdit = class (TEdit)
> private
> FOnLateChange: TNotifyEvent;
> FInterval: cardinal;
> FTimerHWND: HWND;
> procedure FinalizeTimer;
> protected
> procedure DoLateChange;
> procedure UpdateTimer;
> procedure WndProc(var Message: TMessage); override;
> procedure KeyPress(var Key: Char); override;
> public
> destructor Destroy; override;
> published
> property OnLateChange: TNotifyEvent read FOnLateChange write
> FOnLateChange;
> property Interval: cardinal read FInterval write FInterval;

--
______________________________________________________
Karel Kral, vedouci odd. IT / IT manager
Purus, s.r.o., Cezavy 627, 664 56 Blucina, CZ
Tel: 547 235 000, 602 552 432, Fax: 547 231 203
E-Mail: mailto:kral@purus.cz, WWW: http://www.purus.cz
______________________________________________________


Odpovedá: Milan Tomes

22. 10. 2004 8:25

Protoze se zbytecne alokuje dalsi handle pouze pro zachytavani zpravy
WM_TIMER (viz. Classes.AllocateHwnd). Prijde mi to uplne zbytecne  

S pozdravem

Milan Tomes

P.S.: Nemuzu si odpustit rypnuti a podekovat za pochvalu  )))))))))))
Admin - I'm so sorry  
> [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Karel Kral
> Sent: Friday, October 22, 2004 9:19 AM
>
> Diky, pekne a elegantni, urcite se mi to bude hodit. Proc nepouzivas
> TTimer z Delphi?
>
> Milan Tomes napsal(a):
> > Tak tohle povazuji take za dost hruzne reseni.
> > Tady je reseni *BEZ* pouziti ProcessMessages:
> >
> > interface
> >
> > type
> > TMyEdit = class (TEdit)
> > private
> > FOnLateChange: TNotifyEvent;
> > FInterval: cardinal;
> > FTimerHWND: HWND;
> > procedure FinalizeTimer;
> > protected
> > procedure DoLateChange;
> > procedure UpdateTimer;
> > procedure WndProc(var Message: TMessage); override;
> > procedure KeyPress(var Key: Char); override;
> > public
> > destructor Destroy; override;
> > published
> > property OnLateChange: TNotifyEvent read FOnLateChange write
> > FOnLateChange;
> > property Interval: cardinal read FInterval write FInterval;


Odpovedá: Karel Pecinka

22. 10. 2004 8:51

Pouzil jsem reseni Milana a je opravdu super, vrele doporucuji. Trochu
jsem si ho teda upravil, timer se nespousti v KeyPress ale v Change, coz
odchyti i napr. stisk Delete atd. Pridal jsem si, ze kdyz interval je 0
tak se udalost pusti az po Enteru. Do konfigurace jsem si hodil
nastaveni prodlevy, aby si uzivatel podle poctu polozek ceniku,
rychlosti pocitace a rychlosti jeho psani mohl nastavit prodlevu, ktera
mu umozni pracovat s programem co nejpohodlneji. Milanovi moc dekuju.

Co se tyce druheho reseni, je opravdu nic moc. Filtrovani totiz provadim
jednim prikazem a o zbytek se stara komponenta tabulky. Mohl bych se
nabourat do zdrojaku a nejak tam davat to processmessages ale reseni
Milana Tomese je naprosto jednoduche, nevyzaduje zadne upravy kodu a
uzivatel ziskava naproste pohodli pri praci.

Karel

> -----Original Message-----
> From: delphi-l-owner@clexpert.cz
> [mailto:delphi-l-owner@clexpert.cz] On Behalf Of Milan Tomes
> Sent: Friday, October 22, 2004 8:07 AM
> To: delphi-l@clexpert.cz
> Subject: Re: Filtrovani kbmMemTable v druhem vlakne
>
>
> Cele reseni problemu je opravdu zalozeno na startovani
> timeru. Snazil jsem se o reseni elementarniho problemu a sice
> toho aby se se zpozdenim vyvolala udalost OnChange. Pokud se
> Ti toto nelibi, tak se prosim rychle uklidni a prestan s
> takovymito vypady. Netvrdil jsem, ze je to reseni pomoci
> vlakna, protoze se plne ztotoznuji, ze ve vlakne by - kdyz uz
> - melo probihat vlastni cteni dat a ne zpracovani pauzy,
> ktera je uzce zavisla na VCL komponente a tudiz veskere
> volani musi byt provadeno v kontextu hlavniho threadu. Jestli
> je pro Tebe tento kod slozity je samozrejme otazka jina - ja
> osobne vubec nechapu co je na tomto kodu sloziteho - jedna se
> o 6 metod jejichz delka nepresahuje 6 jednoduchych radku
> kodu. BTW cely kod jsem psal v Outlooku a jeho napsani
> netrvalo dele nez 5 minut  
>
> Cele reseni jsem napsal a neustale povazuji Tve reseni za hruzne.
>
> Omlouvam se, ze jsem hluboce urazil Tve city tim, ze jsem
> vyslovil svuj nazor na kvalitu Tveho reseni. Az budes neco
> potrebovat Ty, tak verim, ze se vsichni strasne pretrhnout
> kdyz vidi Tvoji reakci. Ja osobne nepomohu uz jen proto, ze
> se budu obavat abys me nahodou za univerzalnost a tim take
> moznou vetsi narocnost na znalosti a slozitost nahodou znovu
> neserval  
>
> S pozdravem
>
> Milan Tomes
>
> P.S.: Tusim, ze tazatel to jiz vyresil prave vytvoreni one
> nove komponenty, jejiz kod jsem posilal  
> P.P.S.: Podivej se na thread, kde se pouziti
> Application.ProcessMessages velice kritizuje.
>
> > [mailto:delphi-l-owner@clexpert.cz]On Behalf Of Jan Novak
> > Sent: Friday, October 22, 2004 7:45 AM
> >
> > >> Vsechno v pohode zvlada hlavni thread s pouzitim ProcessMessages.
> >
> > > Tak tohle povazuji take za dost hruzne reseni.
> >
> > Nezlob se na mne, ale to, cemu rikas 'reseni' ty, je jen nekolik
> > obrazovek sloziteho kodu, ktere nedelaji nic, nez ze po
> urcitem case
> > od zmeny Editu poslou zpravu hlavnimu threadu. Nemas tam
> vubec nic o
> > tom, jak se od ni v dalsim threadu nastartuje nacitani a jak se
> > pripadne prerusi predchozi nacitani, pokud bylo rozbehnuto.
> Neni tam
> > ani to, jak ten thread po nacteni jedne polozky zobrazi
> jeji obsah v
> > nejakem gridu, ktery je soucasti VCL a tedy se musi volat pres
> > Synchronize.
> >
> > Zkus si to napsat cele a pak se vyslov, co je 'hruzne' a co je
> > prehledne a jasne reseni.
> >
> >
> >
> >
>
>
>